﻿using System;
using System.Diagnostics;
using System.IO;

namespace Engine.Dtd {
    /// <summary>
    /// An Entity declared in a DTD.
    /// </summary>
    [DebuggerDisplay("Name = {Name} Literal = {Literal}")]
    internal sealed class Entity {
        private Entity parent;
        private Uri url;

        /// <summary>
        /// Initializes a new instance of an Entity declared in a DTD.
        /// </summary>
        /// <param name="name">The name of the entity.</param>
        /// <param name="literal">The literal value of the entity.</param>
        public Entity(string name, string literal) {
            Guard.ArgumentNotNull(literal, "literal");
            Name = name;
            Literal = literal;
            }

        /// <summary>
        /// Initializes a new instance of an Entity declared in a DTD.
        /// </summary>
        /// <param name="name">A string that contains the name of the entity.</param>
        /// <param name="baseUri">The base URI for the entity to read from the stream.</param>
        /// <param name="reader">A text reader to read the entity from.</param>
        public Entity(string name, Uri baseUri, TextReader reader) {
            Guard.ArgumentNotNull(baseUri, "baseUri");
            Guard.ArgumentNotNull(reader, "reader");
            Name = name;
            Stream = reader;
            url = baseUri;
            }

        /// <summary>
        /// The name of the entity.
        /// </summary>
        public string Name { get; private set; }

        internal TextReader Stream { get; private set; }

        /// <summary>
        /// The Uri that is the source for this entity.
        /// </summary>
        public Uri Url {
            get {
                if (this.url != null)
                    return this.url;
                else if (parent != null)
                    return parent.Url;
                else
                    return null;
                }
            }

        /// <summary>
        /// Gets the parent Entity of this Entity.
        /// </summary>
        public Entity Parent {
            get { return parent; }
            }

        /// <summary>
        /// Whether this entity is an internal entity or not.
        /// </summary>
        /// <value>true if this entity is internal, otherwise false.</value>
        public bool IsInternal { get; private set; }

        /// <summary>
        /// The literal value of this entity.
        /// </summary>
        public string Literal { get; private set; }


        public void Open(Entity parent) {
            Guard.ArgumentNotNull(parent, "parent");
            this.parent = parent;
            url = parent.url;
            IsInternal = true;
            if (Literal != null)
                Stream = new StringReader(Literal);
            }
        }
    }
